/*****************************************************************************/
/* File: Picture.cpp														 */
/* Author: rszulgo                                                           */
/*                                                                           */
/* Description:																 */
/* A picture is manipulated directly by the end user (instead of			 */
/* the texture). The main difference between a picture and a texture		 */
/* is that the texture can contain multiple pictures (it is the				 */
/* complete file). 															 */
/*****************************************************************************/
#include "Picture.h"
#include "TextureManager.h"

using namespace std;

CPicture::CPicture(const string& strFileName) 
  : m_pTexture(NULL), m_rectTextCoord()
{
	m_pTexture = CTextureManager::GetInstance()->GetTexture(strFileName); 
	m_pTexture->AddReference();
	

	// Set the texture coordinate to the full texture
	m_rectTextCoord.m_Top = m_rectTextCoord.m_Left = 0;
	m_rectTextCoord.m_Bottom = m_pTexture->GetHeight();
	m_rectTextCoord.m_Right = m_pTexture->GetWidth();
}

CPicture::CPicture(const string& strFileName, const TRectanglei& textCoord)
  : m_pTexture(NULL), m_rectTextCoord(textCoord)
{
	m_pTexture = CTextureManager::GetInstance()->GetTexture(strFileName); 
	m_pTexture->AddReference();
}

TPicturePtr CPicture::CreatePicture(const string& strFileName)
{
	TPicturePtr picPtr(new CPicture(strFileName));
	return picPtr;
}

TPicturePtr CPicture::CreatePicture(const string& strFileName, const TRectanglei& textCoord)
{
	TPicturePtr picPtr(new CPicture(strFileName,textCoord));
	return picPtr;
}


CPicture::~CPicture()
{
	if (m_pTexture)
		m_pTexture->ReleaseReference();
}

void CPicture::BlitPicture(int iXOffset, int iYOffset) const
{
	if (m_pTexture)
	{
		m_pTexture->Bind();

		// Get the coordinates of the picture in the texture, expressed
		// as a value from 0 to 1.
		float Top	 = ((float)m_rectTextCoord.m_Top)/m_pTexture->GetHeight();
		float Bottom = ((float)m_rectTextCoord.m_Bottom)/m_pTexture->GetHeight();
		float Left   = ((float)m_rectTextCoord.m_Left)/m_pTexture->GetWidth();
		float Right  = ((float)m_rectTextCoord.m_Right)/m_pTexture->GetWidth();

		// Draw the textured rectangle.
		glBegin(GL_QUADS);

			glTexCoord2f(Left,Top);		
			glVertex3i(iXOffset,iYOffset,0);

			glTexCoord2f(Left,Bottom);	
			glVertex3i(iXOffset,iYOffset+m_rectTextCoord.GetHeight(),0);

			glTexCoord2f(Right,Bottom);	
			glVertex3i(iXOffset+m_rectTextCoord.GetWidth(),iYOffset+m_rectTextCoord.GetHeight(),0);

			glTexCoord2f(Right,Top);	
			glVertex3i(iXOffset+m_rectTextCoord.GetWidth(),iYOffset,0);

		glEnd();
	}
}

void CPicture::BlitPicturePart(int iXOffset, 
						   int iYOffset, 
						   const TRectanglei& part)
{
	// Check if the part is completely in the picture
	assert(part.m_Top>=0);
	assert(part.m_Bottom<=m_rectTextCoord.GetHeight());
	assert(part.m_Left>=0);
	assert(part.m_Right<=m_rectTextCoord.GetWidth());

	if (m_pTexture)
	{
		m_pTexture->Bind();

		TRectanglei newTextRect = part;
		newTextRect.OffsetRect(m_rectTextCoord.m_Left,m_rectTextCoord.m_Top);

		// Get the coordinates of the image in the texture, expressed
		// as a value from 0 to 1.
		float Top	 = ((float)newTextRect.m_Top)/m_pTexture->GetHeight();
		float Bottom = ((float)newTextRect.m_Bottom)/m_pTexture->GetHeight();
		float Left   = ((float)newTextRect.m_Left)/m_pTexture->GetWidth();
		float Right  = ((float)newTextRect.m_Right)/m_pTexture->GetWidth();

		// Draw the textured rectangle.
		glBegin(GL_QUADS);
		glTexCoord2f(Left,Top);		glVertex3i(iXOffset,iYOffset,0);
		glTexCoord2f(Left,Bottom);	glVertex3i(iXOffset,iYOffset+newTextRect.GetHeight(),0);
		glTexCoord2f(Right,Bottom);	glVertex3i(iXOffset+newTextRect.GetWidth(),iYOffset+newTextRect.GetHeight(),0);
		glTexCoord2f(Right,Top);	glVertex3i(iXOffset+newTextRect.GetWidth(),iYOffset,0);
		glEnd();
	}
}

